<template>
	<div class="pro-table">
		<!-- 查询表单 -->
		<div id="header-title">
			<SearchForm :search="search" :reset="reset" v-if="props.searchPosition === 'top'" :searchParam="searchParam"
				:columns="searchColumns" v-show="isShowSearch"></SearchForm>
			<!-- 表格头部 操作按钮 -->
			<div class="table-header">
				<div class="header-button-lf">
					<SearchForm :search="search" :reset="reset" v-if="props.searchPosition === 'header'"
						:searchParam="searchParam" :columns="searchColumns" v-show="isShowSearch"></SearchForm>
					<slot v-else name="tableHeader" :ids="selectedListIds" :selectList="selectedList"
						:isSelected="isSelected">
					</slot>
				</div>
				<div class="header-button-ri" v-if="toolButton">
					<el-button :icon="Refresh" circle @click="getTableList"> </el-button>
					<el-button :icon="Operation" circle @click="openColSetting"> </el-button>
					<el-button :icon="Search" circle v-if="searchColumns.length" @click="isShowSearch = !isShowSearch">
					</el-button>
				</div>
			</div>
		</div>
		<div class="table-body">
			<!-- 表格主体 -->
			<el-table ref="tableRef" :data="tableData" :border="border" @expand-change="onExpandChange"
				@select="selectionChange" @row-dblclick="dblclick" @row-click="click" row-key="id"
				v-loading="loading" height="100%" :stripe="stripe" :default-expand-all="defaultExpandAll"
				:tree-props="{ children: childrenName, hasChildren: 'hasChildren' }">
				<template v-for="item in tableColumns" :key="item">
					<!-- selection || index -->
					<el-table-column v-if="item.type == 'selection' || item.type == 'index'" :type="item.type"
						:selectable="item.selectable" :reserve-selection="item.type == 'selection'" :label="item.label"
						:align="item.align || 'center'" :width="item.width" :fixed="item.fixed">
					</el-table-column>
					<!-- expand（展开查看详情，请使用作用域插槽） -->
					<el-table-column v-if="item.type == 'expand'" :type="item.type" :label="item.label"
						:align="item.align || 'center'" :width="item.width" :fixed="item.fixed" v-slot="scope">
						<slot :name="item.type" :row="scope.row"></slot>
					</el-table-column>
					<!-- other -->
					<el-table-column v-if="!item.type && item.prop && item.isShow" :prop="item.prop" :label="item.label"
						:align="item.align || 'center'" :width="item.width" :sortable="item.sortable"
						:show-overflow-tooltip="item.prop !== 'operation'" :resizable="true" :fixed="item.fixed">
						<!-- 自定义 header (使用组件渲染 tsx 语法) -->
						<template #header v-if="item.renderHeader">
							<component :is="item.renderHeader" :row="item"> </component>
						</template>

						<!-- 自定义配置每一列 slot（使用作用域插槽） -->
						<template #default="scope">
							<slot :name="item.prop" :row="scope.row">
								<!-- 图片(自带预览) -->
								<el-image v-if="item.image" :src="scope.row[item.prop!]"
									:preview-src-list="[scope.row[item.prop!]]" fit="cover" class="table-image"
									preview-teleported />
								<!-- tag 标签（自带格式化内容） -->
								<el-tag v-else-if="item.tag"
									:type="filterEnum(scope.row[item.prop!], item.enum, 'tag')">
									{{
										item.enum?.length ? filterEnum(scope.row[item.prop!], item.enum) :
											defaultFormat(0, 0, scope.row[item.prop!])
									}}
								</el-tag>
								<!-- 文字（自带格式化内容） -->
								<span v-else>
									{{
										item.enum?.length ? filterEnum(scope.row[item.prop!], item.enum) :
											defaultFormat(0, 0, scope.row[item.prop!])
									}}
								</span>
							</slot>
						</template>
					</el-table-column>
				</template>
				<template #empty>
					<!-- <el-empty description="无数据" image-size="80"/> -->
					<p>无数据</p>
				</template>
			</el-table>
		</div>
		<!-- 分页 -->
		<div class="table-page">
			<Pagination v-if="pagination" :pageable="pageable" :handleSizeChange="handleSizeChange"
				:handleCurrentChange="handleCurrentChange"></Pagination>
		</div>
		<!-- 列设置 -->
		<ColSetting v-if="toolButton" ref="colRef" :tableRef="tableRef" :colSetting="colSetting"></ColSetting>
	</div>
</template>

<script setup lang="ts" name="proTable">
import { ref, computed, onMounted } from "vue";
import { useTable } from "/@/hooks/useTable";
import { useSelection } from "/@/hooks/useSelection";
import { Refresh, Operation, Search } from "@element-plus/icons-vue";
import { ColumnProps } from "/@/components/ProTable/interface";
import { filterEnum, defaultFormat } from "/@/utils/util";
import SearchForm from "/@/components/SearchForm/index.vue";
import Pagination from "/@/components/Pagination/index.vue";
import ColSetting from "./components/ColSetting.vue";

// 表格 DOM 元素
const tableRef = ref();

// 是否显示搜索模块
const isShowSearch = ref<boolean>(true);

interface ProTableProps {
	columns: Partial<ColumnProps>[]; // 列配置项
	requestApi: (params: any) => Promise<any>; // 请求表格数据的api ==> 必传
	pagination?: boolean; // 是否需要分页组件 ==> 非必传（默认为true）
	initParam?: any; // 初始化请求参数 ==> 非必传（默认为{}）
	multiple?: boolean;//是否允许多选，默认可以
	initData?: boolean; // 是否自动请求数据==>非必传，默认为true
	defaultExpandAll?: boolean;
	height?: number;
	clickToSelect?: boolean; //单击是否选中
	searchPosition?: string; //搜索位置，top(默认),header
	deep?: string;//如{id:'1', person:{xm:''}}，如需在表格展示xm，则这里需要传person，多个用逗号分隔，columns对应personxm
	border?: boolean; // 表格是否显示边框 ==> 非必传（默认为true）
	stripe?: boolean; // 是否带斑马纹表格 ==> 非必传（默认为false）
	toolButton?: boolean; // 是否显示表格功能按钮 ==> 非必传（默认为true）
	childrenName?: string; // 当数据存在 children 时，指定 children key 名字 ==> 非必传（默认为"children"）
}

// 接受父组件参数，配置默认值
const props = withDefaults(defineProps<ProTableProps>(), {
	columns: () => [],
	pagination: true,
	initParam: {},
	deep: '',
	clickToSelect: false,
	searchPosition: 'top',
	multiple: true,
	initData: true,
	defaultExpandAll: false,
	height: 205,
	border: true,
	stripe: false,
	toolButton: true,
	childrenName: "children"
});

// 表格多选 Hooks
const { selectionChange, getRowKeys, selectedList, selectedListIds, isSelected } = useSelection(tableRef, props.multiple);

// 表格操作 Hooks
const { tableData, extendData, pageable, searchParam, initSearchParam, getTableList, loading, search, reset, handleSizeChange, handleCurrentChange } =
	useTable(props.requestApi, props.initParam, props.pagination, props.initData, props.deep);
// 表格列配置项处理（添加 isShow 属性，控制显示/隐藏）
const tableColumns = ref<Partial<ColumnProps>[]>();
tableColumns.value = props.columns.map(item => {
	return {
		...item,
		isShow: localStorage.getItem(item.prop) !== 'hide'
	};
});

// 过滤需要搜索的配置项
const searchColumns = props.columns.filter(item => item.search);

// 设置搜索表单的默认值
searchColumns.forEach(column => {
	if (column.initSearchParam !== undefined && column.initSearchParam !== null) {
		initSearchParam.value[column.prop!] = column.initSearchParam;
	}
});

// * 列设置
const colRef = ref();
// 过滤掉不需要设置显隐的列
const colSetting = tableColumns.value.filter((item: Partial<ColumnProps>) => {
	return item.type !== "selection" && item.type !== "index" && item.type !== "expand" && item.prop !== "operation";
});
const openColSetting = () => {
	colRef.value.openColSetting();
};

const emit = defineEmits(['dblclick', 'expand-change']);
//双击
const dblclick = (row: any, column: any, event: any) => {
	emit('dblclick', row, column, event)
}
//地址树展开关闭事件
const onExpandChange = (row: any, expanded: any) => {
	emit('expand-change', row, expanded);
}
//单击
const click = (row: any, column: any, event: any) => {
	//是否需要点击选中
	if (props.clickToSelect) {
		const selected = selectedListIds.value.includes(row.id);
		tableRef.value.toggleRowSelection(row, !selected)
		isSelected.value = !selected;
		if (selected) {
			const index = selectedList.value.findIndex((item: any) => item.id === row.id);
			selectedList.value.splice(index, 1)
		} else {
			selectedList.value.push(row);
		}
	}
}

// 暴露给父组件的参数和方法
defineExpose({ searchParam, refresh: getTableList, resetList: reset, getSelectedList: () => selectedList, getTableData: () => tableData, extendData });
</script>

<style scoped lang="scss">
.pro-table {
	width: 100%;
	display: flex;
	flex-direction: column;
	height: 100%;

	.table-body {
		height: 0;
		flex: 1 1 auto;
	}

	.table-page {
		border: 1px solid #efefef;
		border-top: none;
	}
}
</style>